package com.snail.clouds.storage.core;

import com.snail.clouds.storage.auth.LoginCredentials;
import com.snail.clouds.storage.auth.PersistentLoginInfo;
import com.snail.clouds.storage.entity.AccountInfo;
import com.snail.clouds.storage.entity.CloudFile;
import com.snail.clouds.storage.entity.TrashItem;
import com.snail.clouds.storage.exception.AuthException;
import com.snail.clouds.storage.exception.FileException;
import com.snail.clouds.storage.exception.CloudStorageException;

import java.util.List;
import java.util.function.BiConsumer;

/**
 * 云存储客户端抽象基类，所有网盘客户端必须继承此类
 */
public interface AbstractStorageClient {
    /**
     * 检查是否已登录
     *
     * @return 是否已登录
     */
    boolean isLoggedIn();

    /**
     * 触发登录接口（第一阶段）
     *
     * @param credentials 登录凭据
     * @return 登录会话标识符
     * @throws AuthException 登录触发失败
     */
    String triggerLogin(LoginCredentials credentials) throws AuthException;

    /**
     * 检测登录状态接口（第二阶段）
     *
     * @param sessionId 登录会话标识符
     * @return 登录成功时返回持久化信息，否则返回null
     * @throws AuthException 检查登录状态失败
     */
    PersistentLoginInfo checkLoginStatus(String sessionId) throws AuthException;

    /**
     * 登录缓存信息序列化成字符串的接口（第三阶段）
     *
     * @return 序列化后的登录信息字符串
     * @throws AuthException 序列化失败
     */
    String serializeLoginInfo() throws AuthException;

    /**
     * 登录接口恢复接口（第四阶段）
     *
     * @param serializedInfo 序列化后的登录信息字符串
     * @return 恢复是否成功
     * @throws AuthException 恢复登录失败
     */
    boolean restoreLoginFromString(String serializedInfo) throws AuthException;

    /**
     * 刷新访问令牌
     *
     * @return 是否刷新成功
     * @throws AuthException 刷新token失败
     */
    boolean refreshToken() throws AuthException;

    /**
     * 获取账户信息
     *
     * @return 账户信息
     * @throws AuthException 未登录
     */
    AccountInfo getAccountInfo() throws AuthException, CloudStorageException;

    /**
     * 列出文件
     *
     * @param folderId 文件夹ID，根目录ID由上游使用方定义
     * @return 文件列表
     * @throws AuthException  未登录
     * @throws FileException 文件夹不存在
     */
    List<CloudFile> listFiles(String folderId) throws AuthException, FileException, CloudStorageException;

    /**
     * 创建文件夹
     *
     * @param name     文件夹名称
     * @param parentId 父文件夹ID，根目录ID由上游使用方定义
     * @return 创建的文件夹信息
     * @throws AuthException         未登录
     * @throws FileException         父文件夹不存在
     * @throws CloudStorageException 配额已满
     */
    CloudFile createFolder(String name, String parentId) throws AuthException, FileException, CloudStorageException;

    /**
     * 上传文件
     *
     * @param fileName         文件名
     * @param fileData         文件数据
     * @param parentId         父文件夹ID，根目录ID由上游使用方定义
     * @param overwrite        是否覆盖同名文件
     * @param progressCallback 进度回调函数
     * @return 上传后的文件信息
     * @throws AuthException         未登录
     * @throws FileException         父文件夹不存在
     * @throws CloudStorageException 配额已满或网络错误
     */
    CloudFile uploadFile(
            String fileName,
            byte[] fileData,
            String parentId,
            boolean overwrite,
            BiConsumer<Integer, Integer> progressCallback
    ) throws AuthException, FileException, CloudStorageException;

    /**
     * 删除文件
     *
     * @param fileId 文件ID
     * @throws AuthException 未登录
     * @throws FileException 文件不存在
     */
    void deleteFile(String fileId) throws AuthException, FileException;

    /**
     * 移动文件
     *
     * @param fileId      文件ID
     * @param newParentId 新父文件夹ID，根目录ID由上游使用方定义
     * @param folderId    可选，源文件夹ID，用于获取文件信息
     * @return 移动后的文件信息
     * @throws AuthException 未登录
     * @throws FileException 文件或目标文件夹不存在
     */
    CloudFile moveFile(String fileId, String newParentId, String folderId) throws AuthException, FileException;

    /**
     * 重命名文件
     *
     * @param fileId  文件ID
     * @param newName 新文件名
     * @return 重命名后的文件信息
     * @throws AuthException 未登录
     * @throws FileException 文件不存在
     */
    CloudFile renameFile(String fileId, String newName) throws AuthException, FileException;

    /**
     * 获取文件信息
     * 优化：支持在指定文件夹ID下查看文件信息，查询逻辑是扫描该文件夹下的文件列表，查找指定文件ID的文件
     *
     * @param fileId   文件ID
     * @param folderId 文件夹ID，在该文件夹下查找文件
     * @return 文件信息
     * @throws AuthException 未登录
     * @throws FileException 文件不存在
     */
    CloudFile getFileInfo(String fileId, String folderId) throws AuthException, FileException;

    /**
     * 搜索文件
     *
     * @param parentId 父文件夹ID，根目录ID由上游使用方定义
     * @param query    搜索关键词
     * @return 搜索结果
     * @throws AuthException 未登录
     */
    List<CloudFile> searchFiles(String parentId, String query) throws AuthException, CloudStorageException;

    /**
     * 列出回收站文件
     *
     * @return 回收站文件列表
     * @throws AuthException 未登录
     */
    List<TrashItem> listTrash() throws AuthException;

    /**
     * 清空回收站
     *
     * @throws AuthException 未登录
     */
    void emptyTrash() throws AuthException;

    /**
     * 获取文件下载链接
     *
     * @param fileId 文件ID
     * @return 下载链接
     * @throws AuthException 未登录
     * @throws FileException 文件不存在
     */
    String getDownloadUrl(String fileId) throws AuthException, FileException, CloudStorageException;

    /**
     * 检查文件是否可以快速上传（秒传）
     *
     * @param fileName 文件名
     * @param fileData 文件数据
     * @return 是否可以快速上传
     * @throws AuthException 未登录
     */
    boolean checkFastUpload(String fileName, byte[] fileData) throws AuthException;

    /**
     * 快速上传文件（秒传）
     *
     * @param fileName 文件名
     * @param fileData 文件数据
     * @param parentId 父文件夹ID，根目录ID由上游使用方定义
     * @return 上传后的文件信息
     * @throws AuthException         未登录
     * @throws FileException         父文件夹不存在
     * @throws CloudStorageException 快速上传失败
     */
    CloudFile fastUploadFile(String fileName, byte[] fileData, String parentId)
            throws AuthException, FileException, CloudStorageException;
}
